const argsConfig = require('./args.config');
const config = require('./router.config');
const _ = require('lodash');

function isRequired(args) {
  return args['必填'] === '必填';
}

function getReqArgs(method, argsList) {
  let parentNode = null;
  if (method === 'post') parentNode = 'body';
  else if (method === 'get') parentNode = 'query';
  else throw new Error('仅支持 get/post 传参');
  return argsList.filter((obj) => obj['父节点'] === parentNode);
}

function getResArgs(argsList) {
  const parentNode = 'res';
  return argsList.filter((obj) => obj['父节点'] === parentNode);
}

function getResCustomTypeArgs(argsList) {
  const parentNode = 'res';
  return argsList.filter((obj) => obj['父节点'] !== parentNode);
}

function getReqCustomTypeArgs(argsList) {
  return argsList.filter(
    (obj) => obj['父节点'] !== 'body' && obj['父节点'] !== 'query'
  );
}

function getType(type, name = '') {
  const arrayRegx = /\[\]/;
  if (type === 'string' || type === 'boolean') return type;
  else if (type === 'number') return 'integer';
  else if (type === 'string[]') return 'Array<string>';
  else {
    let tempType = type;
    // 是否全局自定义类型
    if (arrayRegx.test(type)) {
      tempType = type.replace('[]', '');
    }
    const globalCustomTypeList = argsConfig['CustomTypes'];
    const index = globalCustomTypeList.findIndex(
      (obj) => obj['父节点'] === tempType
    );
    // 不是全局类型
    if (index === -1) {
      // 不是全局类型
      type = _.upperFirst(name) + _.upperFirst(type);
    } else {
      // 全局类型
      type = _.upperFirst(type);
    }
    // 判断全局自定义类型是否是数组
    if (arrayRegx.test(type)) return `Array<${type.replace('[]', '')}>`;
    else return `${type}.model`;
  }
}

function genCustomTypeSwaggerJsDoc(argsList, prexfix = '') {
  let result = '';
  // 先map当前接口的所有类型（父节点）
  let parentNodes = argsList.map((args) => args['父节点']);
  // 过滤掉 body query res
  parentNodes = parentNodes.filter(
    (obj) => obj !== 'body' || obj !== 'query' || obj !== 'res'
  );
  // 剩下的类型做去重操作
  parentNodes = [...new Set(parentNodes)];
  // 依次生成文档
  for (const parentNode of parentNodes) {
    result += `/**\n * @typedef ${_.upperFirst(prexfix)}${_.upperFirst(
      parentNode
    )}\n`;
    const childList = argsList.filter((obj) => obj['父节点'] === parentNode);
    for (const args of childList) {
      const rawType = args['类型'];
      const type = getType(rawType);
      result += ` * @property {${type}} ${args['参数名']}${
        isRequired(args) ? '.required' : ''
      } - ${args['描述']}\n`;
    }
    result += ` */\n`;
  }
  return result;
}

module.exports = function genSwaggerJsDoc() {
  const modules = config.modules;
  let swaggerJsDocList = [];
  // 全局的自定义类型定义
  const globalCustomTypeList = argsConfig['CustomTypes'];
  const globalCustomTypeDef = genCustomTypeSwaggerJsDoc(globalCustomTypeList);
  swaggerJsDocList.push(globalCustomTypeDef);

  for (const moduleObj of modules) {
    const baseUrl = moduleObj.baseUrl;
    const group = moduleObj.group;
    const routers = moduleObj.routers;
    const moduleName = moduleObj.name || moduleObj.baseUrl;
    let customTypeForReq = new Set();
    for (const router of routers) {
      const name = router.name;
      const method = router.method;
      const url = router.url;
      const title = router.title;
      const summary = router.summary;

      // 生成 swaggerJsDocForRouter 接口描述信息
      let swaggerJsDocForRouter = `/**
 * ${title}
 *
 * @group ${group}
 * @summary ${summary}
 * @route ${method.toUpperCase()} /${baseUrl}/${url}\n`;
      const argsList = argsConfig[name].argsList;
      const reqArgs = getReqArgs(method, argsList);
      // 生成 swaggerJsDocForRouter 请求参数部分
      for (const args of reqArgs) {
        const rawType = args['类型'];
        const type = getType(rawType, moduleName);
        swaggerJsDocForRouter += ` * @param {${type}} ${args['参数名']}.${
          args['父节点']
        }${isRequired(args) ? '.required' : ''} - ${args['描述']}\n`;
        customTypeForReq.add(type);
      }
      // 生成 swaggerJsDocForRouter 响应部分
      const resModelName = `${_.upperFirst(name)}Response`;
      swaggerJsDocForRouter += ` * @return {${resModelName}.model} - 200 - 请求成功\n */\n`;

      swaggerJsDocList.push(swaggerJsDocForRouter);

      // req 中的自定义类型添加类型
      const reqCustomTypeArgsList = getReqCustomTypeArgs(argsList);
      // 自定义类型添加 typedef
      const customTypeDefForReq = genCustomTypeSwaggerJsDoc(
        reqCustomTypeArgsList,
        name
      );
      swaggerJsDocList.push(customTypeDefForReq);

      // 生成 ResponseForXXX 的 typedef
      const resList = argsConfig[name].resList;
      const resArgsList = getResArgs(resList);
      let swaggerJsDocForRes = `/**\n * @typedef ${resModelName}\n`;
      for (const args of resArgsList) {
        const rawType = args['类型'];
        const type = getType(rawType, name);
        swaggerJsDocForRes += ` * @property {${type}} ${args['参数名']}${
          isRequired(args) ? '.required' : ''
        } - ${args['描述']}\n`;
      }
      swaggerJsDocForRes += ' */\n';
      swaggerJsDocList.push(swaggerJsDocForRes);
      // res 中的自定义类型添加类型
      const resCustomTypeArgsList = getResCustomTypeArgs(resList);
      // 自定义类型添加 typedef
      const customTypeDefForRes = genCustomTypeSwaggerJsDoc(
        resCustomTypeArgsList,
        name
      );
      swaggerJsDocList.push(customTypeDefForRes);
    }
  }
  return swaggerJsDocList.join('\n');
};
